#include "SoundPlayer.h"


void SoundPlayer::appendBuffer(SoundBuffer & sb)
{
	synchronized (this)
	{
		buffers.push_back(&sb);
	}
}


int SoundPlayer::run()
{
	double delayAccum = 0.0;
	int numBufWritten = 0;
	double numOfBuffersInListAcc = 0.0;
	int numBuffersSizeIterations = 0;

	WAVEFORMATEX pFormat;
	pFormat.wFormatTag=WAVE_FORMAT_PCM;     // simple, uncompressed format
	pFormat.nChannels=1;                    //  1=mono, 2=stereo
	pFormat.nSamplesPerSec=sampleRate;      // 16000
	pFormat.nAvgBytesPerSec=sampleRate*2;   // = nSamplesPerSec * n.Channels * wBitsPerSample/8
	pFormat.nBlockAlign=2;                  // = n.Channels * wBitsPerSample/8
	pFormat.wBitsPerSample=16;              //  16 for high quality, 8 for telephone-grade
	pFormat.cbSize=0;

	while (buffers.size() < numOfBuffersOnInit && !mustTerminate()) Sleep(1);
	std::cout << "Playing...";

	MMRESULT hRes = waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0L, 0L, WAVE_FORMAT_DIRECT);

	std::list <SoundBuffer *>::iterator todo_iter = buffers.begin();
	std::list <SoundBuffer *>::iterator last_iter;

	while (!mustTerminate())
	{
		numOfBuffersInListAcc += buffers.size();
		numBuffersSizeIterations++;

		if (todo_iter != buffers.end())
		{
			WAVEHDR & WaveInHdr = (*todo_iter)->WaveInHdr;
			hRes = waveOutPrepareHeader(hWaveOut, &WaveInHdr, sizeof(WAVEHDR));
			hRes = waveOutWrite(hWaveOut, &WaveInHdr, sizeof(WAVEHDR));

			last_iter = todo_iter;
			todo_iter++;
		}
		else
		{
			std::list <SoundBuffer *>::iterator it = last_iter;
			it++;
			if (it != buffers.end()) todo_iter = it;
		}


		std::list <SoundBuffer *>::iterator it = buffers.begin();
		if (waveOutUnprepareHeader(hWaveOut, &(*it)->WaveInHdr, sizeof(WAVEHDR))!=WAVERR_STILLPLAYING)
		{
			delayAccum += GetTickCount() - (*it)->timestamp;
			numBufWritten++;

			(*it)->available = true;	//libera buffer

			synchronized (this)
			{
				buffers.erase(it);
			}
		}

		Sleep(1);
	}


	waveOutClose(hWaveOut);


	std::cout	<< "Recording finished! " << std::endl
				<< "avg(Player.DelayTime) = " << (delayAccum/numBufWritten)
				<< " ms [better: ~ " << numOfBuffersOnInit << " * " << timeOfEachBuffer << " ms ??]" << std::endl
				<< "avg(Player.BufferListLen) = " << (numOfBuffersInListAcc / numBuffersSizeIterations)
				<< " [better: ~ " << numOfBuffersOnInit << " ??]" << std::endl
				<< std::endl;

	return 0;
}
